package com.meis.widget.praise;

import com.meis.widget.ResourceTable;
import ohos.aafwk.ability.Ability;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Image;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Point;
import ohos.app.Context;

import java.security.SecureRandom;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by wenshi on 2018/7/10.
 * Description 贝塞尔点赞动画
 */
public class BezierPraiseAnimator {

    // 上下文
    private Context mContext;

    // 控件树的顶层视图
    private ComponentContainer mRootView;

    // 随机数
    private SecureRandom mRandom;

    // 点赞的小图标资源
    private Element[] mDrawables;

    // 目标控件在窗口中的X坐标
    private int mTargetX;

    // 目标控件在窗口中的Y坐标
    private int mTargetY;

    // 点赞小图标的宽高
    private int mPraiseIconWidth = 50;
    private int mPraiseIconHeight = 50;

    private int mAnimatorDuration = 1000;

    private DependentLayout.LayoutConfig config;
    private ShapeElement transBG;

    public BezierPraiseAnimator(Context context, ComponentContainer rootView) {
        mContext = context;
        if (context instanceof Ability) {
            mRootView = rootView;
        } else {
            throw new RuntimeException("context is not instanceof for Ability");
        }
        initData();
    }

    public BezierPraiseAnimator(ComponentContainer rootView) {
        mContext = rootView.getContext();
        mRootView = rootView;
        initData();
    }

    private void initData() {
        mRandom = new SecureRandom();
        try {
            initIcons();
        } catch (Exception ignored) {
        }
    }

    /**
     * 获取当前targetView在屏幕中的位置
     *
     * @param targetView targetView
     */
    public void startAnimation(Component targetView) {
        // 获取targetView在屏幕中的位置
        int[] loc = targetView.getLocationOnScreen();
        int viewHeight = targetView.getHeight();
        int viewWidth = targetView.getWidth();
        // 设置起始坐标，中点坐标
        mTargetX = loc[0] + viewWidth / 2 - mPraiseIconWidth / 2;
        mTargetY = loc[1] + viewHeight / 2 - mPraiseIconHeight / 2;

        // 播放点赞动画
        DependentLayout group = createPraiseGroup();
        startPraiseAnimation(group);
    }

    /**
     * 屏幕坐标
     *
     * @param screenX screenX
     * @param screenY screenY
     */
    public void startAnimation(int screenX, int screenY) {
        mTargetX = screenX;
        mTargetY = screenY;
        DependentLayout group = createPraiseGroup();
        startPraiseAnimation(group);
    }

    private void startPraiseAnimation(DependentLayout group) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                mContext.getUITaskDispatcher().asyncDispatch(() -> mRootView.removeComponent(group));
            }
        }, mAnimatorDuration);
    }

    // 播放点赞动画
    private DependentLayout createPraiseGroup() {
        int size = mRandom.nextInt(4) + (mDrawables.length - 4);
        if (config == null) {
            int matchParent = DependentLayout.LayoutConfig.MATCH_PARENT;
            config = new DependentLayout.LayoutConfig(matchParent, matchParent);
        }
        DependentLayout group = new DependentLayout(mRootView.getContext());
        group.setLayoutConfig(config);
        for (int i = 0; i < size; i++) {
            // 动态添加点赞小图标
            Image praiseIv = new Image(mContext);
            praiseIv.setImageElement(mDrawables[mRandom.nextInt(mDrawables.length)]);
            praiseIv.setLayoutConfig(new ComponentContainer.LayoutConfig(mPraiseIconWidth, mPraiseIconHeight));
            group.addComponent(praiseIv);
            // 设置点赞小图标的动画并播放
            AnimatorGroup praiseAnimator = getPraiseAnimator(praiseIv);
            praiseAnimator.start();
        }
        if (mRootView.getChildCount() > 0) {
            mRootView.addComponent(group, 1);
        } else {
            mRootView.addComponent(group, 0);
        }
        return group;
    }

    /**
     * 获取到点赞小图标动画
     *
     * @param target 动画所属的Component
     * @return AnimatorGroup
     */
    private AnimatorGroup getPraiseAnimator(Component target) {
        // 获取贝塞尔曲线动画
        AnimatorValue bezierPraiseAnimator = getBezierPraiseAnimator(target);
        // 组合动画（旋转动画+贝塞尔曲线动画）旋转角度（200~720）
        int rotationAngle = mRandom.nextInt(520) + 200;
        AnimatorValue rotationAnimator = new AnimatorValue();
        rotationAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        rotationAnimator.setValueUpdateListener((animatorValue, v) -> {
            int angle = rotationAngle % 2 == 0 ? rotationAngle : -rotationAngle;
            target.setRotation(v * angle);
        });
        // 组合动画
        AnimatorGroup composeAnimator = new AnimatorGroup();
        composeAnimator.runParallel(bezierPraiseAnimator, rotationAnimator);
        composeAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        composeAnimator.setDuration(mAnimatorDuration);
        return composeAnimator;
    }

    private AnimatorValue getBezierPraiseAnimator(final Component target) {
        // 构建贝塞尔曲线的起点，控制点，终点坐标
        float startX = mTargetX;
        float startY = mTargetY - 220;
        int random = mRandom.nextInt(mPraiseIconWidth);
        float endX;
        float endY;
        float controlX;
        float controlY;
        controlY = startY - mRandom.nextInt(500) - 100;
        // 左右两边
        if (random % 2 == 0) {
            endX = mTargetX - random * 8;
            controlX = mTargetX - random * 2;
        } else {
            endX = mTargetX + random * 8;
            controlX = mTargetX + random * 2;
        }
        endY = mTargetY + random + 220;
        PraiseEvaluator evaluator = new PraiseEvaluator(new Point(controlX, controlY));
        AnimatorValue animator = new AnimatorValue();
        animator.setCurveType(Animator.CurveType.ANTICIPATE);
        Point start = new Point(startX, startY);
        Point end = new Point(endX, endY);
        animator.setValueUpdateListener((animatorValue, v) -> {
            Point result = evaluator.evaluate(v, start, end);
            target.setContentPositionX(result.getPointX());
            target.setContentPositionY(result.getPointY());
            // 设置透明度 [1~0]
            target.setAlpha(1.0F - v);
        });
        animator.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {
                target.setAlpha(0);
            }

            @Override
            public void onCancel(Animator animator) {
                target.setAlpha(0);
            }

            @Override
            public void onEnd(Animator animator) {
                target.setAlpha(0);
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        return animator;
    }

    // 初始化点赞小图标
    private void initIcons() throws Exception {
        mDrawables = new Element[14];
        mDrawables[0] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_1));
        mDrawables[1] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_2));
        mDrawables[2] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_3));
        mDrawables[3] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_4));
        mDrawables[4] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_5));
        mDrawables[5] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_6));
        mDrawables[6] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_7));
        mDrawables[7] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_8));
        mDrawables[8] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_9));
        mDrawables[9] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_10));
        mDrawables[10] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_11));
        mDrawables[11] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_12));
        mDrawables[12] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_13));
        mDrawables[13] = new PixelMapElement(mContext.getResourceManager().getResource(ResourceTable.Media_mei_ic_praise_14));
    }
}
